package com.lynn.salary.dao;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.lynn.salary.util.BeansInterface;
import com.lynn.salary.util.ResultAnalysis;
import com.lynn.salary.util.SQLCreator;

public class CommonDao implements ICommonDao, BeansInterface {

	public ThreadLocal<Connection> connection = new ThreadLocal<Connection>();

	public <T> T getById(Class<T> c, Serializable id) throws SQLException, NoSuchMethodException, IllegalAccessException,
			InvocationTargetException {
		String pkName = null;
		try {
			Method getPkName = c.getMethod("getPkName");
			pkName = (String) getPkName.invoke(c);
		} catch (Exception e) {
			System.err.println("CommonDao::getById反射调用静态方法出错");
			return null;
		}

		String condition = pkName + "='" + id + "'";
		List<T> r = getList(c, condition);
		if (r != null && r.size() == 1)
			return r.get(0);
		return null;
	}

	public <T> List<T> getList(Class<T> c, String condition) throws SQLException, NoSuchMethodException, IllegalAccessException,
			InvocationTargetException {
		String fields[] = null;
		try {
			Method getFields = c.getMethod("getFields");
			fields = (String[]) getFields.invoke(c);
		} catch (Exception e1) {
			System.err.println("CommonDao::getList反射调用静态方法出错");
			return null;
		}
		List<Map<String, Object>> tmp = getPartList(c, fields, condition);
		ResultAnalysis ra = new ResultAnalysis();
		List<T> result = ra.analysis(tmp, c);
		return result;
	}

	public <T> Map<String, Object> getPartById(Class<T> c, String[] part, Serializable id) throws SQLException, NoSuchMethodException,
			IllegalAccessException, InvocationTargetException {
		String pkName = null;
		try {
			Method getPkName = c.getMethod("getPkName");
			pkName = (String) getPkName.invoke(c);
		} catch (Exception e) {
			System.err.println("CommonDao::getById反射调用静态方法出错");
			return null;
		}

		String condition = pkName + "=?";
		List<Map<String, Object>> r = getPartList(c, part, condition, id);
		if (r != null && r.size() == 1)
			return r.get(0);
		return null;
	}

	public <T> List<Map<String, Object>> getPartList(Class<T> c, String[] part, String condition) throws SQLException,
			NoSuchMethodException, IllegalAccessException, InvocationTargetException {
		if (part == null || part.length == 0) {
			System.err.println("CommonDao::getPartList字段列表为空错误");
			return null;
		}
		SQLCreator creator = new SQLCreator("SELECT", c, part, condition);
		creator.build();
		String sql = creator.createSQL();

		return executeSQL(sql);
	}
	
	public <T> List<Map<String, Object>> getPartList(Class<T> c, String[] part, String condition, Object... values) throws SQLException,
			NoSuchMethodException, IllegalAccessException, InvocationTargetException {
		if (part == null || part.length == 0) {
			System.err.println("CommonDao::getPartList字段列表为空错误");
			return null;
		}
		SQLCreator creator = new SQLCreator("SELECT", c, part, condition);
		creator.build();
		String sql = creator.createSQL();

		return prepareExecuteSQL(sql, values);
	}
	

	public <T> T save(T o) throws SQLException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
		SQLCreator creator = new SQLCreator("INSERT", o);
		creator.build();
		String sql = creator.createSQL();

		prepareExecuteUpdateSQL(sql, creator.getValues().toArray());

		return o;
	}

	@SuppressWarnings("unchecked")
	public <T> T save(Class<T> c, Map<String, Object> data) throws SQLException, NoSuchMethodException, IllegalAccessException,
			InvocationTargetException {
		SQLCreator creator = new SQLCreator("INSERT", c, data);
		creator.build();
		String sql = creator.createSQL();

		prepareExecuteUpdateSQL(sql, creator.getValues().toArray());

		return (T) creator.getInsertObject();
	}

	public <T> boolean update(Class<T> c, Map<String, Object> data) throws SQLException, NoSuchMethodException, IllegalAccessException,
			InvocationTargetException {
		SQLCreator creator = new SQLCreator("UPDATE", c, data);
		creator.build();
		String sql = creator.createSQL();
		prepareExecuteUpdateSQL(sql, creator.getValues().toArray());
		return true;
	}

	public <T> boolean update(T o) throws SQLException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
		SQLCreator creator = new SQLCreator("UPDATE", o);
		creator.build();
		String sql = creator.createSQL();
		prepareExecuteUpdateSQL(sql, creator.getValues().toArray());
		return true;
	}

	public <T> boolean delete(Class<T> c, String condition) throws SQLException, NoSuchMethodException, IllegalAccessException,
			InvocationTargetException {
		SQLCreator creator = new SQLCreator("DELETE", c, condition);
		creator.build();
		String sql = creator.createSQL();
		executeUpdateSQL(sql);
		return true;
	}

	public <T> boolean deleteById(Class<T> c, Serializable id) throws SQLException, NoSuchMethodException, IllegalAccessException,
			InvocationTargetException {

		String pkName = null;
		try {
			Method getPkName = c.getMethod("getPkName");
			pkName = (String) getPkName.invoke(c);
		} catch (Exception e) {
			System.err.println("CommonDao::deleteById出错");
			return false;
		}
		delete(c, pkName + "='" + id + "'");
		return true;
	}

	public List<Map<String, Object>> executeSQL(String sql) throws SQLException {
		Connection cont = connection.get();
		Statement stat = null;
		ResultSet r = null;
		try {
			stat = cont.createStatement();
			System.err.println("executeSQL:" + sql);
			r = stat.executeQuery(sql);
		} catch (SQLException e) {
			System.err.println("CommonDao::getById执行SQL出错");
			throw e;
		}

		ResultAnalysis ra = new ResultAnalysis();

		List<Map<String, Object>> result = ra.analysis(r);
		return result;
	}

	public List<Map<String, Object>> prepareExecuteSQL(String sql, Object... values) throws SQLException {
		Connection cont = connection.get();
		PreparedStatement stat = null;
		ResultSet r = null;
		try {
			System.out.println("prepareExecuteSQL:" + sql);
			stat = cont.prepareStatement(sql);
			for (int i = 0; i < values.length; i++) {
				Object so = values[i];
				stat.setObject(i + 1, so);
			}
			System.err.println(stat);
			r = stat.executeQuery();
		} catch (SQLException e) {
			e.printStackTrace();
			System.err.println("CommonDao::executeUpdateSQL执行SQL出错");
			throw e;
		}
		
		ResultAnalysis ra = new ResultAnalysis();

		List<Map<String, Object>> result = ra.analysis(r);
		return result;
	}

	public void executeUpdateSQL(String sql) throws SQLException {
		Connection cont = connection.get();
		Statement stat = null;
		ResultSet r = null;
		try {
			stat = cont.createStatement();
			System.err.println("executeUpdateSQL:" + sql);
			stat.executeUpdate(sql);
		} catch (SQLException e) {
			e.printStackTrace();
			System.err.println("CommonDao::executeUpdateSQL执行SQL出错");
			throw e;
		}
	}

	public void prepareExecuteUpdateSQL(String sql, Object ... values) throws SQLException {
		Connection cont = connection.get();
		PreparedStatement stat = null;
		try {
			System.out.println("prepareExecuteSQL:" + sql);
			stat = cont.prepareStatement(sql);
			for (int i = 0; i < values.length; i++) {
				Object so = values[i];
				stat.setObject(i + 1, so);
			}
			System.err.println(stat);
			stat.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
			System.err.println("CommonDao::executeUpdateSQL执行SQL出错");
			throw e;
		}
	}

	public void setConnection(Connection conn) {
		this.connection.set(conn);
	}

	public void setDao(ICommonDao dao) {

	}

	public void setTarget(Object o) {

	}

	public void destory() {
		System.out.println("\t\tCommonDao destory completed ... ");
		
	}

	public <T> List<T> conver(Class<T> clazz, List<Map<String, Object>> data) throws Exception {
		
		List<T> results = new ArrayList<T>();
		if(data == null || data.size() == 0) {
			return results;
		}
		ResultAnalysis ra = new ResultAnalysis();
		results = ra.analysis(data, clazz);
		
		
		return results;
	}

}
